package cn.dfun.demo.scdemo.ali.order.controller;

import cn.dfun.demo.scdemo.ali.order.service.PaymentService;
import cn.dfun.demo.scdemo.common.entity.CommonResult;
import cn.dfun.demo.scdemo.common.entity.Payment;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@Slf4j
public class AliOrderController {
    @Resource
    private RestTemplate restTemplate;
    @Value("${service-url.scdemo-ali-payment}")
    private String serviceUrl;
    @Resource
    private PaymentService paymentService;

    @GetMapping("/fallback/payment/{id}")
    // 未配置fallback方法直接报异常
//    @SentinelResource(value = "fallback")
    // 只指定降级方法
//    @SentinelResource(value = "fallback", fallback = "handleFallback")
    // 只指定限流方法,第一次请求抛异常,限流后被blockHandler处理
//    @SentinelResource(value = "fallback", blockHandler = "handleBlock")
    // 同时指定限流降级方法,第一次请求被降级,限流后被blockHandler处理
//    @SentinelResource(value = "fallback", blockHandler = "handleBlock", fallback = "handleFallback")
    @SentinelResource(value = "fallback", blockHandler = "handleBlock", fallback = "handleFallback",
        // 忽略异常
        exceptionsToIgnore={IllegalArgumentException.class})
    public CommonResult fallback(@PathVariable Long id) {
        String url = serviceUrl + "/payment/" + id;
        CommonResult result = restTemplate.getForObject(url, CommonResult.class, id);
        if(id == 4) {
            throw new IllegalArgumentException("非法参数");
        } else if(result.getData() == null) {
            throw new NullPointerException("空指针");
        }
        return result;
    }

    /**
     * 降级处理
     */
    public CommonResult handleFallback(@PathVariable Long id, Throwable e) {
        Payment payment = new Payment(id, "null");
        String msg = "handleFallback, exception: " + e.getMessage();
        return CommonResult.success(msg, payment);
    }

    /**
     * 限流处理
     */
    public CommonResult handleBlock(@PathVariable Long id, BlockException e) {
        Payment payment = new Payment(id, "null");
        String msg = "handleBlock, exception: " + e.getMessage();
        return CommonResult.success(msg, payment);
    }

    @GetMapping(value="/consumer/payment/{id}")
    CommonResult<Payment> getById(@PathVariable("id") Long id) {
        return paymentService.getById(id);
    }
}
